#pragma once

#include <stdio.h>

namespace proxy {
    
/// @brief 抽象主题类, 用于声明真实主题和代理对象实现的业务方法
class AbstractSubject {
public:
    virtual ~AbstractSubject() {}
    virtual void Request() = 0;
};

/// @breif 真实主题类, 实现了抽象主题中的具体业务，是代理对象所代表的真实对象，是最终要引用的对象
class RealSubject : public AbstractSubject {
public:
    virtual void Request() {
        printf("this is RealSubject::Request!\n");
    }
};

// @breif 代理类, 提供了与真实主题相同的接口，其内部含有对真实主题的引用，它可以访问、控制或扩展真实主题的功能
class SubjectProxy : public AbstractSubject {
public:
    virtual ~SubjectProxy() {
        if (real_) delete real_; 
    }
    virtual void Request() {
        if (!real_) real_ = new RealSubject();
        PreRequest();
        real_->Request();
        PostRequest();
    }
    virtual void PreRequest() {
        printf("this is SubjectProxy::PreRequest!\n");
    }
    virtual void PostRequest() {
        printf("this is SubjectProxy::PostRequest!\n");
    }

private:
    RealSubject* real_;
};

} // namespace proxy

void Test_06_proxy_impl_1() {
    printf("-------------------- %s --------------------\n", __FUNCTION__);
    proxy::AbstractSubject* ptr = new proxy::SubjectProxy();
    ptr->Request();
    delete ptr;
}

// -------------------- Test_06_proxy_impl_1 --------------------
// this is SubjectProxy::PreRequest!
// this is RealSubject::Request!
// this is SubjectProxy::PostRequest!